class Perplexity
  include Comparable

  attr_accessor :val
  def initialize vv
    self.val = vv
  end

  def to_i
    return Math::E**@val
  end

  def + second
    return Perplexity.new self.val if second == Perplexity.inf
    return Perplexity.new second.val if self == Perplexity.inf
    smaller, bigger = [self.val, second.val].sort
    Perplexity.new bigger + Math.log( 1 + Math::E**(smaller - bigger) )
  end

  def - second
    if self.val > second.val
      return Perplexity.new( self.val +
        Math.log( 1 - Math::E**(second.val - self.val) ) )
    end
    raise "I dont know "+self.val.to_s+" - "+second.val.to_s+" = ???"
  end

  def * second
    return Perplexity.new self.val + second.val
  end

  def / second
    return Perplexity.new self.val - second.val
  end

  def <=> second
    return self.val <=> second.val
  end

  def self.test
    a = Perplexity.new Math.log 0.6
    b = Perplexity.new Math.log 0.3
    apb = a + b
    bpa = b + a
    amb = a * b
    bma = b * a
    adb = a / b
    bda = b / a
    amnb = a - b
    infa = @@INF + a
    ainf = a + @@INF
    raise "Summ not work"    unless apb.to_i == 0.9 and bpa.to_i == 0.9
    raise "Multipy not work" unless amb.to_i == 0.18 and bma.to_i == 0.18
    raise "Divide not work" unless adb.to_i == 2.0 and bda.to_i == 0.5
    raise "minus not work" unless (amnb.to_i - 0.3).abs < 0.00001
    raise "comaprable not work" unless a > b
    raise "inf not working" unless @@INF < b and @@INF < amb
    raise "summ with inf not simmetrical" unless infa == ainf
    raise "summ with inf is wrong" unless (infa.to_i-ainf.to_i).abs <0.0001 && (infa.to_i-a.to_i).abs <0.0001
    begin
      bmna = b - a
      raise "smaller - bigger not work"
    rescue RuntimeError
    end
  end

  def self.from_i vv
    Perplexity.new Math.log vv
  end

  def self.to_perpelx_val vv
    Math.log vv
  end

  @@INF = Perplexity.from_i 0
  def self.inf
    @@INF
  end
end

